// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: daniel

#include "coin2/exchange/lmax_digital/api_util/auth_key.h"

#include <fmt/format.h>

#include "coin2/base/base64.h"
#include "coin2/base/time.h"
#include "coin2/exchange/base/api_util/api_signature.h"
#include "coin2/exchange/base/api_util/json_writer.h"
#include "coin2/exchange/base/api_util/nonce_manager.h"

auto LmaxdigitalBaseAuth::GenSignature(
    const std::string& access_key,
    const std::string& nonce_str,
    const std::string& ts_str,
    const std::string& secret_key) const -> std::string {
  return ApiSignatureUtil::GetSignatureByHmacSHA256(
      fmt::format("{}{}{}", access_key, nonce_str, ts_str),
      impl::base64_decode(secret_key));
}

auto LmaxdigitalBaseAuth::GenBodyJsonString() const -> std::string {
  auto nonce_str = std::to_string(impl::NonceManager::Get());
  auto ts_str = Iso8601FromTimestamp(GetCurrentTimestamp());
  ts_str = fmt::format("{}Z", ts_str.substr(0, ts_str.length() - 6));
  JsonWriter jw;
  jw.PutString("client_key_id", access_key_);
  jw.PutString("timestamp", ts_str);
  jw.PutString("nonce", nonce_str);
  jw.PutString("signature", GenSignature(access_key_, nonce_str, ts_str, secret_key_));
  return jw.ToJsonString();
}

AsioHttpContext* LmaxdigitalRestAuth::CreateRequestByGetWithSignature(
    const std::string& address,
    UrlParamsBuilder* builder) {
  std::string query_string = builder->ComputeQueryString();
  std::string target = address;
  if (!query_string.empty()) {
    target += "?" + query_string;
  }
  HeaderSet header = {{"Authorization", fmt::format("Bearer {}", GetToken())}};
  auto ahc = AsioHttpContext::NewGet(host_, port_, bind_ip_, target, header);
  ahc->keep_user_agent = true;
  return ahc;
}

AsioHttpContext* LmaxdigitalRestAuth::CreateRequestByPostWithSignature(
    const std::string& address,
    UrlParamsBuilder* builder) {
  std::string query_string = builder->ComputeQueryString();
  std::string target = address;
  if (!query_string.empty()) {
    target += "?" + query_string;
  }
  HeaderSet header = {{"Content-Type", "application/json"}};
  auto ahc = AsioHttpContext::NewPost(host_, port_, bind_ip_, target, header, GenBodyJsonString());
  ahc->keep_user_agent = true;
  return ahc;
}
